#include "smse2kincludes.h"
#include "KSSFile.h"


CKSSFile::~CKSSFile() {
	if (maincode) delete[] maincode;
	if (bankcode) delete[] bankcode;

	Msg("CKSSFile deleted\n");
}

int CKSSFile::Open(const char* fn) {
	this->fHandle = filesystem.OpenFile(fn,FSYS_PERMISSION_READ);

	if (!fHandle) return 1;

	// size of file
	UINT64 filesize = filesystem.GetFileSize(fHandle);

	filesystem.Read(fHandle,(UINT8*)&this->header,0x20);

	if (!memcmp(&this->header.header,KSS_TYPE_KSCC,4)) {
		Msg("KSS filetype: KSCC. File header details:\n");
		Msg("Load Offset: %04X\tLoad Size: %04X\n",header.load_offset,header.load_size);
		Msg("Init Address: %04X\tPlay Address: %04X\n",header.init_addr,header.play_addr);
		
		if (header.bank_count) {
			Msg("Page information present\n");
			
			if (header.bank_count & 0x80) {
				header.banksize = 0x2000; // 8 kb banks	
				Msg("Bank size: 8 KB\n");
			} else {
				header.banksize = 0x4000; // 16 kb banks
				Msg("Bank size: 16 KB\n");
	

			}
			Msg("First bank ID: %d\n",header.first_bank);
		} else {
			Msg("Code is not banked\n");
		}

		if (header.flags & KSCC_SMS_MODE) {
			Msg("System: Sega Master System / Game Gear\n");
			if (header.flags & KSCC_YM2413) Msg("Yamaha YM2413 present\n");
			if (header.flags & KSCC_GAMEGEAR_STEREO) Msg("GameGear Stereo enabled\n");

		} else {
			Msg("System: MSX\n");
			if (header.flags & KSCC_YM2413) Msg("Yamaha YM2413 present\n");
			if (header.flags & KSCC_RAM) Msg("Extra RAM present\n");
			if (header.flags & KSCC_MSXAUDIO) Msg("MSX-AUDIO present\n");

		}


	} else {
		Msg("KSS file format unrecognized, dying hilariously\n");
		filesystem.CloseFile(fHandle);
		return 1;
	}

	// Get main code
	filesystem.Seek(fHandle, 0x10); // KSCC version, but whatever
	
	maincode = new CMemory;
	if (maincode->AllocMemory(header.load_size)) {
		Msg("can't alloc memory\n");
		
		return 1;
	}

	filesystem.Read(fHandle,maincode->GetRawMemory(),header.load_size);

	// Read in the banked code
	bankcode = new CMemory;

	
	bankcode->AllocMemory( filesize - header.load_size - 0x10 );
	filesystem.Read(fHandle, bankcode->GetRawMemory(), filesize - header.load_size - 0x10);
	

	filesystem.CloseFile(fHandle);
	return 0;
}

KSSHeader* CKSSFile::GetHeader() {
	return &this->header;
}

CMemory* CKSSFile::GetMainCode() {
	return this->maincode;
}

CMemory* CKSSFile::GetBankedData() {
	return this->bankcode;
}